package com.mycompany.delivery.web;

import com.mycompany.delivery.dto.ContactDTO;
import com.mycompany.delivery.servicelayer.ContactService;
import com.mycompany.delivery.validation.ContactSpringValidator;
import java.util.ArrayList;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.util.UriComponentsBuilder;

import javax.validation.Valid;
import java.util.List;
import java.util.Locale;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.validation.Validator;
import org.springframework.web.util.UriUtils;

/**
 * SpringMVC Controller for handling books.
 *
 * @author Martin Hunek
 */
@Controller
@RequestMapping("/contact")
public class ContactController {

    final static Logger log = LoggerFactory.getLogger(ContactController.class);
/*
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.addValidators(new ContactSpringValidator());
    }
*/
    @Autowired
    private ContactService contactServices;

    @Autowired
    private MessageSource messageSource;

    @ModelAttribute("contacts")
    public List<ContactDTO> allContact() {
        log.debug("allContacts()");
        return contactServices.getAllContacts();
    }

    public void debugCurrentLogin() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null) {
            String name = auth.getName(); //get logged in username
            log.debug(name + " logged");
            for (GrantedAuthority s : auth.getAuthorities()) {
                log.debug(s.getAuthority());
            }
        } else {
            log.debug("nobody logged");
        }
    }

    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public String list(Model model) {
        debugCurrentLogin();
        log.debug("list()");
        model.addAttribute("contact", new ContactDTO());
        return "contact/list";
    }

    @RequestMapping(value = "/delete/{id}", method = RequestMethod.POST)
    public String delete(@PathVariable long id, RedirectAttributes redirectAttributes, Locale locale, UriComponentsBuilder uriBuilder) {
        log.debug("delete({})", id);
        ContactDTO contact = contactServices.find(id);
        contactServices.remove(contact);
        redirectAttributes.addFlashAttribute(
                "message",
                messageSource.getMessage("contact.delete.message", new Object[]{contact.getName(), contact.getSurname(), contact.getId()}, locale)
        );
        return "redirect:" + uriBuilder.path("/contact/list").build();
    }

    @RequestMapping(value = "/update/{id}", method = RequestMethod.GET)
    public String update_form(@PathVariable long id, Model model) {
        ContactDTO contact = contactServices.find(id);
        model.addAttribute("contact", contact);
        log.debug("update_form(model={})", model);
        return "contact/edit";
    }

    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public String update(@Valid @ModelAttribute ContactDTO contact, BindingResult bindingResult, Model model,RedirectAttributes redirectAttributes, Locale locale, UriComponentsBuilder uriBuilder) {
        log.debug("update(locale={}, contact={})", locale, contact);
        ContactSpringValidator validator = new ContactSpringValidator();
        validator.validate(contact, bindingResult);

        if (bindingResult.hasErrors()) {
            log.debug("binding errors");
            for (ObjectError ge : bindingResult.getGlobalErrors()) {
                log.debug("ObjectError: {}", ge);
            }
            for (FieldError fe : bindingResult.getFieldErrors()) {
                log.debug("FieldError: {}", fe);
                
           model.addAttribute("contact", contact);
           String mailmessage = messageSource.getMessage(fe,  locale);
           model.addAttribute("message", mailmessage);
            }

            
            return contact.getId() == null ? "contact/list" : "contact/edit";
        }

   
        if (contact.getId() == null) {
            contactServices.create(contact);
            redirectAttributes.addFlashAttribute(
                    "message",
                    messageSource.getMessage("contact.add.message", new Object[]{contact.getName(), contact.getSurname(), contact.getId()}, locale)
            );
        } else {
            contactServices.update(contact);
            redirectAttributes.addFlashAttribute(
                    "message",
                    messageSource.getMessage("contact.updated.message", new Object[]{contact.getName(), contact.getSurname(), contact.getId()}, locale)
            );
        }
        return "redirect:" + uriBuilder.path("/contact/list").build();
    }

    @RequestMapping(value = "/find", method = RequestMethod.GET)
    public String findDef(Model model) {
        model.addAttribute("string", new String());

        model.addAttribute("contacts", new ArrayList<ContactDTO>());
        log.debug("find(model={})", model);
        return "contact/find";
    }

    @RequestMapping(value = "/find/{name}", method = RequestMethod.GET)
    public String findDef(@PathVariable String name, Model model, UriComponentsBuilder builder, Locale locale) {

        model.addAttribute("string", new String());
        log.debug("atribut {} loc {}", name, locale);
        model.addAttribute("contacts", contactServices.findContactBySurname(name));
        log.debug("find(model={})", model);
        return "contact/find";
    }

    @RequestMapping(value = "/find", method = RequestMethod.POST)
    public String finded(@RequestParam("name") String name, Model model, UriComponentsBuilder builder, Locale locale) {

        String n = name;
        log.debug("atribut1 {} loc {}", name, locale);
        try {
            n = UriUtils.encodePath(name, "UTF-8");
        } catch (Exception ex) {
        }
        log.debug("atribut2 {}", n);
        log.debug("find(model={})", model);

        return "redirect:" + builder.path("/contact/find/" + n).build();
    }

}
